#ifndef DYN_ROOTS_HUNTING_H
#define DYN_ROOTS_HUNTING_H

#include "../utilities/dyn_functor.h"
#include "dyn_roots.h"

/*! \author Joey Dumont <joey.dumont@gmail.com>
 *
 *  \date 2012-10-09
 *
 *  \brief Hunts for a root in a given interval.
 *
 * Given an interval \f$[x_1,x2]\f$, we hunt
 * for a root of the given function. The algorithms
 * selects a subinterval of width \f$\Delta x\f$, supplied
 * by the user, from \f$x_1\f$ and looks for a sign
 * change. If there is no sign change, we look at
 * the next subinterval.
 *
 * If there is a sign change, it means that a root
 * (or singularity), is in this interval. We then use
 * standard bisection to converge to this root (up to a certain
 * point). After we have converged, we evaluate the function
 * at the given point. If it near zero, we accept the root.
 *
 * If it is not,  we reject the root (it is probably
 * a singularity). The criterion for root dismissal
 * is supplied by the user. We thus jump ahead, avoiding
 * the singularity in the hunt.
 *
 * When we have attained a proper root, we use
 * a few iterations of the Newton-Raphson method
 * to polish the root. Since we are already close,
 * we are almost guaranteed convergence.
 */

class Hunting : public RootFinding
{
public:
    /*! The constructor defines the appropriate variables. */
    Hunting(Functor& _func,
            Functor& _derivative,
            double _initialPoint,
            double _endPoint,
            double _scanningSpeed,
            double _tolBis,
            double _tolQuad,
            double _maxValue,
            int _maxIterations);

    /*! @name Accessor Functions. */
    //@{
    Functor& getFunction(){return function;}
    Functor& getDerivative(){return derivative;}
    double getEndPoint(){return endPoint;}
    double getScanningSpeed(){return scanningSpeed;}
    double getToleranceBis(){return toleranceBis;}
    double getMaxValue(){return maximumValue;}

    void setFunction(Functor& _func){function=_func;}
    void setDerivative(Functor& _func){derivative=_func;}
    void setEndPoint(double _endPoint){endPoint=_endPoint;}
    void setScanningSpeed(double _scanningSpeed){scanningSpeed=_scanningSpeed;}
    void setToleranceBis(double _tolBis){toleranceBis=_tolBis;}
    void setMaxValue(double _maxValue){maximumValue=_maxValue;}
    //@}

    /*! Re-declaration of solve(). */
    int solve();

protected:
    /*! @name Specialized variables. */
    //@{
    Functor& function;
    Functor& derivative;
    double endPoint,scanningSpeed,toleranceBis,maximumValue;
    //@}
};

#endif // DYN_ROOTS_HUNTING_H
